/**
 * 目标：
 *  1.通过json传递进来实现
 *  2.组件都可以配置
 *  3.使用方式还是跟原来一样，传参formProps forItemProps 等 抽取使用的放在外层
 *  4.表单验证题可以滚动第一个验证不过的地方
 *  传参注意：
 *  1.form对象 需要传入
 *  2.formItems 可以传入 主要是为了 transformValues
 *  3.onSubmit 可以传入 是默认的处理方式 已经transformValues 因为已经复写了onSubmit
 * @description form表单封装
 * @Author: linzy
 * @Date: 2022-05-12
 * @function useForm
 * @param {string} title - 表单标题
 * @param {object} form - form对象
 * @param {formItem[]} formItems - form表单项数组
 * @param {function} onSubmit - 提交表单事件回调
 * @param {button[]} buttons - 表单保存按钮组
 * @param {button[]} extraButtons - 表单额外保存按钮组 放在保存的右边 可用于重置、编辑等
 *  数组中 可以添加isSubmit 来判断是否需要需要提交表单
 *  数组中 可以添加valid 来判断是否需要验证表单 传递onSubmit回调 isSubmit
 * @param {boolean} disabled - 是否禁用整个表单
 * @param {object} formItemsProps - formItems传参对象
 * @param {object} formItemProps - formItem组件传参对象
 * @param {object} buttonsProps - 表单保存按钮组传参对象
 * @param {ReactDOM} children - 自定义render
 * @param {object} rowProps - Row组件传参对象
 * @param {number} span - Col组件span属性
 * @param {object} buttonsFormItemProps - 按钮formItem组件传参对象
 * @param {boolean} loading - 表单提交时的loading
 * @returns {[]} [Form, formProps, transformDetail];
 * @example
const formRef = useRef();
const formItems = [
  { label: "名称", name: "name1", type: "input", required: true },
  { label: "时间", name: "name2", type: "datetime", required: true },
  { label: "图片", name: "name5", type: 'upload',required: true},
  { label: "下拉", name: "name11", type: "input", required: true },
  { label: "多选", name: "name13", type: "checkbox",
    options:[
      {label: '选项1', value: 1},
    ]
  },
  { label: "备注", name: "name12", type: "textarea" },
];
const [Form, formProps, transformDetail] = useForm({formItems,ref: formRef});
<Form {...formProps} />
 */
import React from "react";
import { Form } from "antd";
import { transformValues, typeOf, transformDetail } from "@/hooks/tools";
import { useFormItems, useButtons } from "@/hooks";
import { setOutAttrs, getValidNameList, setDefaultAttrs } from "@/hooks/tools";
import _ from "lodash";
import { Spin } from "antd";

function useForm(props) {
  const {
    title,
    form,
    formItems,
    onSubmit,
    buttons,
    extraButtons = [],
    disabled,
    formItemsProps = {},
    formItemProps = {},
    buttonsProps = {},
    enterButtonProps = {},
    children,
    rowProps,
    span,
    buttonsFormItemProps,
    loading,
    formLoading = false,
    buttonText,
    ...restProps
  } = props;
  const { validateFieldsAndScroll } = form;
  // 处理 formItemsProps
  setOutAttrs(formItemsProps, {
    formItems,
    form,
    disabled,
    rowProps,
    span,
    formItemProps
  });
  // 处理 buttonsProps buttons 可以为false null等设置为空
  if (typeOf(buttons) === "array") {
    buttonsProps.buttons = buttons;
  } else if (buttons === undefined) {
    // 处理extraButtons onClick
    extraButtons.forEach((item, index) => {
      item.isSubmit === true &&
        setDefaultAttrs(item, {
          onClick: () => {
            overrideSubmit(item.valid, item.onSubmit);
          }
        });
    });
    buttonsProps.buttons = [
      {
        onClick() {
          overrideSubmit();
        },
        disabled: disabled,
        text: buttonText || "保存",
        loading,
        ...enterButtonProps
      },
      ...extraButtons
    ];
  } else {
    buttonsProps.buttons = [];
  }
  disabled && (buttonsProps.disabled = true);
  buttonsProps.payload = form;
  const formItemRender = useFormItems({ ...formItemsProps });
  const buttonsRender = useButtons(buttonsProps);
  function overrideSubmit(valid = true, callback) {
    var validNameList = valid ? getValidNameList(formItems) : [];
    validateFieldsAndScroll(validNameList, (err, values) => {
      if (!err) {
        const newValues =
          formItemsProps.formItems?.length > 0
            ? transformValues(values, formItemsProps.formItems)
            : values;
        if (callback) {
          callback(newValues);
        } else {
          onSubmit && onSubmit(newValues);
        }
      }
    });
  }
  return (
    <>
      {formLoading && (
        <div
          style={{
            textAlign: "center",
            position: "absolute",
            zIndex: 9999,
            top: "25%",
            left: "50%",
            transform: "translate(-50%, -50%)"
          }}
        >
          <Spin size="large" />
        </div>
      )}
      {title && <h3>{title}</h3>}
      <Form
        {...restProps}
        onSubmit={e => {
          e.preventDefault();
          overrideSubmit();
        }}
      >
        {children ? (
          children
        ) : (
          <>
            {formItemRender}
            {/* {disabled !== true && ( */}
            <Form.Item {...buttonsFormItemProps}>{buttonsRender}</Form.Item>
            {/* )} */}
          </>
        )}
      </Form>
    </>
  );
}
const UserFormWrap = Form.create()(useForm);
export default props => {
  return [UserFormWrap, props, transformDetail];
};
